﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gqq.CSharpindepth2.DesignPatterns
{
    public delegate void CatCryEventHandler();
    public interface IObserver
    {
        void Action();
    }

    /// <summary>
    /// 为了简单期间，暂时改成了Cat。
    /// 严格应该定义一个抽象类Subject，在抽象类中定义事件即可。
    /// 接口中是不能有事件的。
    /// </summary>
    public abstract class Observer2
    {
        public abstract void Regist(Cat sub);
    }

    public interface ISubject
    {
        void Notify();
    }

    public class Cat : ISubject
    {
        //猫有一个事件CatCry，在猫执行Cry方法时诱发。
        //它的观察者只要去注册这个事件就可以了。
        public event CatCryEventHandler CatCry;

        public List<IObserver> Observer { get; set; }

        public void Cry()
        {
            Console.WriteLine("cat is crying...");
            Notify();
            if (CatCry != null) CatCry();
        }

        public static void DoTest()
        {
            Cat cat = new Cat();
            new Master2().Regist(cat);
            new Mouse2().Regist(cat);
            cat.Cry();
        }

        public void Notify()
        {
            if (Observer != null)
                foreach (IObserver observer in Observer)
                {
                    observer.Action();
                }
        }
    }

    public class Master2 : Observer2
    {
        public override void Regist(Cat sub)
        {
            sub.CatCry += () => Console.WriteLine("waken...");
        }
    }
    public class Mouse2 : Observer2
    {
        public override void Regist(Cat sub)
        {
            sub.CatCry += () => Console.WriteLine("running...");
        }
    }

    public class Master : IObserver
    {

        public void WakeUp()
        {
            Console.WriteLine("master is waking...");
        }

        public void Action()
        {
            WakeUp();
        }
    }

    public class Mouse : IObserver
    {
        public void Action()
        {
            Run();
        }

        private void Run()
        {
            Console.WriteLine("mouse is running...");
        }
    }


}

